package com.zhuhjay.app.web.controller.system;

import com.zhuhjay.common.base.controller.BaseController;
import com.zhuhjay.common.base.exception.BasicBusinessException;
import com.zhuhjay.common.web.annotation.Matching;
import com.zhuhjay.common.web.annotation.RecordLog;
import com.zhuhjay.common.web.enums.MatchingMode;
import com.zhuhjay.common.web.model.vo.PageInfoVo;
import com.zhuhjay.service.system.model.domain.FileInfo;
import com.zhuhjay.service.system.model.dto.FileChunkDto;
import com.zhuhjay.service.system.model.dto.MdChunkDto;
import com.zhuhjay.service.system.model.vo.CheckChunkVo;
import com.zhuhjay.service.system.model.vo.DirInfoVo;
import com.zhuhjay.service.system.model.vo.FilesCounterInfoVo;
import com.zhuhjay.service.system.model.vo.MdFileInfoVo;
import com.zhuhjay.service.system.service.SystemFileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.hibernate.validator.constraints.Range;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.util.List;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author Zhuhjay
 * @since 2023-02-25
 */
@Api(tags = "文件系统")
@Validated
@RestController
@RequestMapping("/file")
public class SystemFileController extends BaseController {

    @Resource
    private SystemFileService fileService;

    @RecordLog("文件上传检查(FileSystem)")
    @ApiOperation("文件上传检查(FileSystem)")
    @GetMapping("upload/{dirId}")
    @PreAuthorize("@perm.hasPerm('user:worker:fs:file:upload')")
    public CheckChunkVo uploadCheck(
            @PathVariable @NotBlank(message = "未给出具体存放目录") String dirId,
            @Valid FileChunkDto chunkInfo) {
        return fileService.check(dirId, chunkInfo);
    }

    @ApiOperation("文件上传(FileSystem)")
    @PostMapping("upload/{dirId}")
    @PreAuthorize("@perm.hasPerm('user:worker:fs:file:upload')")
    public void upload(
            @PathVariable @NotBlank(message = "未给出具体存放目录") String dirId,
            @Valid FileChunkDto chunkInfo) {
        fileService.fileUpload(dirId, chunkInfo);
    }

    @ApiOperation("修改文件名")
    @PutMapping("rename/{fileId}/{name}")
    @PreAuthorize("@perm.hasPerm('user:worker:fs:file:rename')")
    public void rename(
            @PathVariable @NotBlank(message = "未给出具体移动文件") String fileId,
            @PathVariable @Matching(MatchingMode.FileName) String name) {
        fileService.rename(fileId, name);
    }

    @ApiOperation("文件拷贝/可批量")
    @PostMapping("copy/{dirId}")
    @PreAuthorize("@perm.hasPerm('user:worker:fs:file:copy')")
    public void copy(
            @PathVariable @NotBlank(message = "未给出具体拷贝到文件夹") String dirId,
            @RequestBody List<String> fileIds) {
        if (fileIds == null || fileIds.isEmpty()) {
            throw new BasicBusinessException("未给出具体拷贝文件");
        }
        fileService.copy(fileIds, dirId);
    }

    @ApiOperation("文件移动/可批量")
    @PostMapping("move/{dirId}")
    @PreAuthorize("@perm.hasPerm('user:worker:fs:file:move')")
    public void move(
            @PathVariable @NotBlank(message = "未给出具体移动到文件夹") String dirId,
            @RequestBody List<String> fileIds) {
        if (fileIds == null || fileIds.isEmpty()) {
            throw new BasicBusinessException("未给出具体移动文件");
        }
        fileService.move(fileIds, dirId);
    }

    @ApiOperation("纳入回收站/可批量")
    @DeleteMapping("delete")
    @PreAuthorize("@perm.hasPerm('user:worker:fs:file:delete')")
    public void delete2Recycle(@RequestBody List<String> fileIds) {
        if (fileIds == null || fileIds.isEmpty()) {
            throw new BasicBusinessException("未给出具体删除文件");
        }
        fileService.delete2Recycle(fileIds);
    }

    @ApiOperation("回收站列表")
    @GetMapping("recycle")
    @PreAuthorize("@perm.hasPerm('user:worker:fs:file:recycle')")
    public DirInfoVo recycleList() {
        return fileService.recycleList();
    }

    @ApiOperation("回收站文件还原/可批量")
    @PostMapping("recycle")
    @PreAuthorize("@perm.hasPerm('user:worker:fs:file:recycle')")
    public void recycleRestore(@RequestBody List<String> fileIds) {
        if (fileIds == null || fileIds.isEmpty()) {
            throw new BasicBusinessException("未给出具体还原文件");
        }
        fileService.recycleRestore(fileIds);
    }

    @ApiOperation("回收站文件彻底删除/可批量")
    @DeleteMapping("recycle")
    @PreAuthorize("@perm.hasPerm('user:worker:fs:file:recycle')")
    public void recycleDelete(@RequestBody List<String> fileIds) {
        if (fileIds == null || fileIds.isEmpty()) {
            throw new BasicBusinessException("未给出具体删除文件");
        }
        fileService.recycleDelete(fileIds);
    }

    @ApiOperation("MarkDown文件保存")
    @PostMapping("markdown/upload/{dirId}")
    @PreAuthorize("@perm.hasPerm('user:worker:mdeditor:file:save')")
    public MdFileInfoVo markdownUpload(
            @PathVariable @NotBlank(message = "未给出具体存放目录") String dirId,
            @RequestBody @Valid MdChunkDto chunkInfo) {
        return fileService.markdownUpload(dirId, chunkInfo);
    }

    @ApiOperation("MarkDown文件信息获取")
    @GetMapping("markdown/{fileId}")
    @PreAuthorize("@perm.hasPerm('user:worker:mdeditor:file:info')")
    public MdFileInfoVo markdown(@PathVariable @NotBlank(message = "未给出具体文件") String fileId) {
        return fileService.markdown(fileId);
    }

    @ApiOperation("MarkDown文件分页列表")
    @GetMapping("markdown/page/{pageNum}/{pageSize}")
    @PreAuthorize("@perm.hasPerm('user:console:mdlist')")
    public PageInfoVo<MdFileInfoVo> markdownPage(
            @PathVariable @Range(min = 1, max = Integer.MAX_VALUE) Integer pageNum,
            @PathVariable @Range(min = 5, max = 30) Integer pageSize) {
        return fileService.markdownPage(pageNum, pageSize);
    }

    // ----------------- 管理员操作 -----------------

    @ApiOperation("文件系统统计")
    @GetMapping("counter")
    @PreAuthorize("@perm.hasPerm('system:manager:file:counter')")
    public FilesCounterInfoVo counter() {
        return fileService.counter();
    }

}
